﻿using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Text;
using Microsoft.SharePoint;
using System.Collections.Generic;

namespace OrganizationChartUsingGoogleAPI.OrganizationChart
{
    public static class ConvertTo
    {
        /// <summary>
        /// Convert the object type in the given type and handle the DBNULL.
        /// </summary>
        /// <typeparam name="T">Type to convert</typeparam>
        /// <param name="value">value</param>
        /// <returns>converted value and if DBNULL then return the type's default value i.e. string = string.Empty, Int16=0 </returns>
        public static T CastIn<T>(this object value) where T : IConvertible
        {
            if (value == DBNull.Value)
                if (typeof(T) == typeof(string))
                {
                    return (T)Convert.ChangeType(string.Empty, typeof(T));
                }
                else
                {
                    return default(T);
                }


            if (typeof(T) == typeof(bool))
                return (T)Convert.ChangeType(Convert.ToInt32(value), typeof(T));

            return (T)Convert.ChangeType(value, typeof(T));
        }
    }

    public partial class OrganizationChartUserControl : UserControl
    {
        //Get the List name to fetch the data from
        string listName = "OrgChart_Demo";
        int iRowCounter = 0;
        string sAllNewRows = string.Empty;

        protected void Page_Load(object sender, EventArgs e)
        {
            //Fetch the data (recursively) from the list
            GetNode(string.Empty);

            //Generate the Client Script and Register
            GenerateClientScript(sAllNewRows);
        }

        private void GenerateClientScript(string sAllNewRows)
        {
            string csName1 = "OrgChartScript";
            Type csType = this.GetType();

            ClientScriptManager cs = Page.ClientScript;

            // Check to see if the startup script is already registered. 
            if (!cs.IsStartupScriptRegistered(csType, csName1))
            {
                StringBuilder cstext = new StringBuilder();
                cstext.Append("<script type='text/javascript' src='https://www.google.com/jsapi'></script>");
                cstext.Append("<script type='text/javascript'>");
                cstext.Append("google.load('visualization', '1', { packages: ['orgchart'] });");
                cstext.Append("google.setOnLoadCallback(drawChart);");

                cstext.Append("function drawChart() {");
                cstext.Append("var data = new google.visualization.DataTable();");

                cstext.Append("data.addColumn('string', 'Name');");
                cstext.Append("data.addColumn('string', 'Manager');");
                cstext.Append("data.addColumn('string', 'ToolTip');");
                cstext.Append("var rowArr = new Array();");

                cstext.Append(sAllNewRows);

                cstext.Append("data.addRows(rowArr);");

                cstext.Append("var chart = new google.visualization.OrgChart(document.getElementById('chart_div'));");
                cstext.Append("chart.draw(data, { allowHtml: true, allowCollapse: true });");
                cstext.Append("}");
                cstext.Append("</script>");
                cs.RegisterClientScriptBlock(csType, csName1, cstext.ToString(), false);

            }

        }

        private void GetNode(string reportsTo)
        {
            SPListItemCollection itemCol = GetListItems(listName, reportsTo);

            foreach (SPListItem item in itemCol)
            {
                //create a new row
                sAllNewRows += createNewRow(item);

                //Recursion
                GetNode(item["Name"].ToString());
            }

        }

        private string createNewRow(SPListItem listItem)
        {
            string sName = ConvertTo.CastIn<string>(listItem["Name"]);
            string sTitle = ConvertTo.CastIn<string>(listItem["Title"]);
            string sMoreInfo = ConvertTo.CastIn<string>(listItem["MoreInfo"]);
            //string sReportsTo = ConvertTo.CastIn<string>(listItem["ReportsTo"]);
            string sReportsTo = new SPFieldLookupValue(ConvertTo.CastIn<string>(listItem["ReportsTo"])).LookupValue;

            StringBuilder sText = new StringBuilder();
            sText.Append("var NewRow = new Array();");
            sText.Append(String.Format("NewRow.push({{ v: '{0}', f: '{1}<div style=\"color:red; font-style:italic\">{2}</div>' }});", sName, sName, sTitle));
            sText.Append(String.Format("NewRow.push('{0}');", sReportsTo));
            sText.Append(String.Format("NewRow.push('{0}');", sMoreInfo));
            sText.Append(String.Format("rowArr[{0}] = NewRow;", iRowCounter));

            iRowCounter++;
            return sText.ToString();
        }

        private SPListItemCollection GetListItems(string destList, string reportsTo)
        {
            SPListItemCollection ResultListItems = null;

            using (SPSite oSite = new SPSite(SPContext.Current.Web.Url))
            {
                using (SPWeb oWeb = oSite.OpenWeb())
                {
                    SPList list = oWeb.Lists.TryGetList(destList);
                    if (null == list)
                        return ResultListItems;

                    //Check if the item already exist.
                    StringBuilder sCAMLQuery = new StringBuilder(string.Empty);
                    sCAMLQuery.Append("<Where>");
                    if (reportsTo != string.Empty)
                    {
                        sCAMLQuery.Append("<Eq>");
                        sCAMLQuery.Append("<FieldRef Name='ReportsTo' />");
                        sCAMLQuery.Append("<Value Type='Lookup'>" + reportsTo + "</Value>");
                        sCAMLQuery.Append("</Eq>");
                    }
                    else
                    {
                        sCAMLQuery.Append("<IsNull>");
                        sCAMLQuery.Append("<FieldRef Name='ReportsTo' />");
                        sCAMLQuery.Append("</IsNull>");
                    }
                    sCAMLQuery.Append("</Where>");

                    SPQuery QueryResult = new SPQuery();
                    QueryResult.Query = sCAMLQuery.ToString();
                    ResultListItems = list.GetItems(QueryResult);
                }
            }

            return ResultListItems;
        }
    }
}
